/**
 * 
 */
package dk.itu.mobile.client;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author niebje
 *
 */
public class TcpClient {// implements Runnable {
	
	private int port;
	private Socket socket;
	private DataOutputStream dataOutputStream;
	private DataInputStream dataInputStream;
	private ObjectInputStream objectInputStream;
	private ObjectOutputStream objectOuputStream;
	
	private String lastRequest;
	private String requestBody;
	private String requestType;
	public String lastResult;
	private Object requestObject;
	
	public TcpClient(int port) {
		this.port = port;
		startClient();
	}
	
	private void startClient() {
		try {
			InetAddress serverAddress = InetAddress.getByName("localhost");
			socket = new Socket(serverAddress, port);
	    } catch (IOException ex) {
            ex.printStackTrace();
        } 
	}
	/**
	 * @param type: Task or User
	 * @param operation GET, DELETE
	 * @param taskID An id of an existing task, or of a new task to be created (POST)
	 */
	public void taskListOps(String type, String operation, String body) {
		requestBody = body;
		requestType = type;
		lastRequest = operation;
		request(operation);
		listen();
	}
	/**
	 * 
	 * @param type: Task or User
	 * @param operation: PUT, POST
	 * @param object the object that needs to be updated on the server. In case
	 * of put, the id or name property of the object is used for server side mapping.
	 */
	public void takListObjOps(String type, String operation, Object object) {
		requestType = type;
		lastRequest = operation;
		requestObject = object;
		request(operation);
		listen();
	}
	
	private void request(String message) {
		try {
			dataOutputStream = new DataOutputStream(socket.getOutputStream());
			dataOutputStream.writeUTF(message);
			dataOutputStream.flush();			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}	
	
	private void objectRequest() {
		try {
			objectOuputStream = new ObjectOutputStream(socket.getOutputStream());
			objectOuputStream.writeObject(requestObject);
			objectOuputStream.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		listen();
	}
	
	private void listen() {
		try {
			if ( dataInputStream == null)
				dataInputStream = new DataInputStream(socket.getInputStream());
			String message = dataInputStream.readUTF();
			handleResponse(message);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void objectListen() {
		try {
			objectInputStream = new ObjectInputStream(socket.getInputStream());
			Object object = objectInputStream.readObject();
			System.out.println(object.toString());
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void handleResponse(String message) {
		if (message.equals(lastRequest) && lastRequest.equals("GET")) {
			request(requestType+","+requestBody);
			requestType =""; 
			requestBody ="";
			if (lastRequest.equals("GET")) {
				lastRequest ="";
				objectListen();
			} else {
				lastRequest ="";
				listen();
			}
		} else if ( message.equals(lastRequest) && (lastRequest.equals("PUT")
				|| lastRequest.equals("POST"))) {
			objectRequest();
		}
		else {
			lastResult = message;
			System.out.println(lastResult);
		}
	}
}
